crontab – matoken's blog https://matoken.org/blog Is there no plan B? Mon, 05 Jul 2021 21:18:16 +0000 ja hourly 1 https://wordpress.org/?v=6.8.3 https://matoken.org/blog/wp-content/uploads/2025/03/cropped-1865f695c4eecc844385acef2f078255036adccd42c254580ea3844543ab56d9-32x32.jpeg crontab – matoken's blog https://matoken.org/blog 32 32 speedtest-cli が crontab で動作しなくて困る https://matoken.org/blog/2021/07/06/trouble-with-speedtest-cli-not-working-with-crontab/ https://matoken.org/blog/2021/07/06/trouble-with-speedtest-cli-not-working-with-crontab/#comments Mon, 05 Jul 2021 21:18:14 +0000 http://matoken.org/blog/?p=3287

インターネット速度計測サイトのSpeedtest.net というサイトがあります.

世界中にあるサーバのうち自分のアドレスから近いであろうサーバを選んで速度計測をしてくれるサービスです.

このサービスをcli で実行できるPython製 speedtest-cli というApache 2.0ライセンスのサードパーティのツールがあります.Debianだとパッケージもあるので導入も簡単です.

$ sudo apt install speedtest-cli
$ speedtest-cli -h
usage: speedtest-cli [-h] [--no-download] [--no-upload] [--single] [--bytes] [--share] [--simple] [--csv] [--csv-delimiter CSV_DELIMITER]
                     [--csv-header] [--json] [--list] [--server SERVER] [--exclude EXCLUDE] [--mini MINI] [--source SOURCE] [--timeout TIMEOUT]
                     [--secure] [--no-pre-allocate] [--version]

Command line interface for testing internet bandwidth using speedtest.net.
-------------------------------------------------------------------------- https://github.com/sivel/speedtest-cli

optional arguments:
  -h, --help            show this help message and exit
  --no-download         Do not perform download test
  --no-upload           Do not perform upload test
  --single              Only use a single connection instead of multiple. This simulates a typical file transfer.
  --bytes               Display values in bytes instead of bits. Does not affect the image generated by --share, nor output from --json or
                        --csv
  --share               Generate and provide a URL to the speedtest.net share results image, not displayed with --csv
  --simple              Suppress verbose output, only show basic information
  --csv                 Suppress verbose output, only show basic information in CSV format. Speeds listed in bit/s and not affected by --bytes
  --csv-delimiter CSV_DELIMITER
                        Single character delimiter to use in CSV output. Default ","
  --csv-header          Print CSV headers
  --json                Suppress verbose output, only show basic information in JSON format. Speeds listed in bit/s and not affected by --bytes
  --list                Display a list of speedtest.net servers sorted by distance
  --server SERVER       Specify a server ID to test against. Can be supplied multiple times
  --exclude EXCLUDE     Exclude a server from selection. Can be supplied multiple times
  --mini MINI           URL of the Speedtest Mini server
  --source SOURCE       Source IP address to bind to
  --timeout TIMEOUT     HTTP timeout in seconds. Default 10
  --secure              Use HTTPS instead of HTTP when communicating with speedtest.net operated servers
  --no-pre-allocate     Do not pre allocate upload data. Pre allocation is enabled by default to improve upload performance. To support systems
                        with insufficient memory, use this option to avoid a MemoryError
  --version             Show the version number and exit
matoken@t430s:/media/matoken/rootfs/home/matoken/Videos$

出力オプションで,csvやjsonで書き出すことも可能です.

$ speedtest-cli (1)
Retrieving speedtest.net configuration...
Testing from freebit (203.0.113.0)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by OpenGW (Shizuoka) [64.23 km]: 82.301 ms
Testing download speed................................................................................
Download: 1.51 Mbit/s
Testing upload speed......................................................................................................
Upload: 0.95 Mbit/s
$ speedtest-cli --simple (2)
Ping: 68.211 ms
Download: 8.11 Mbit/s
Upload: 0.84 Mbit/s
$ speedtest-cli --list | grep -i japan | grep -Ei 'kagoshima|miyazaki|kumamoto|ooita|fukuoka|saga|hitoyoshi' (3)
 8407) Allied Telesis Capital Corporation (Sagamihara, Japan) [175.03 km]
35106) yoshis.jp (KDDI-NET) (Fukuoka, Japan) [687.23 km]
38134) NousagiNetwork(@_0rze) (Fukuoka, Japan) [687.23 km]
38947) Rikimoto (Fukuoka, Japan) [687.23 km]
18709) extride inc (Hitoyoshi, Japan) [705.48 km]
$ speedtest-cli --simple --server 18709 (4)
Ping: 122.31 ms
Download: 6.01 Mbit/s
Upload: 0.81 Mbit/s
$ speedtest-cli --csv-header (5)
Server ID,Sponsor,Server Name,Timestamp,Distance,Ping,Download,Upload,Share,IP Address
$ speedtest-cli --csv (6)
42842,Mamireimu Net Work's,Nara,2021-06-23T09:15:44.814808Z,177.32698372902544,86.096,8215354.331324884,1350756.2707027544,,203.0.113.0
$ speedtest-cli --json | jq . (7)
{
  "download": 7961762.454176666,
  "upload": 1054738.8634894243,
  "ping": 73.207,
  "server": {
    "url": "http://speedtestooklaserverjapannagoyashizuoka.baobivawpvojawvianoipwqnpibvbqoubwuvbqasciboabowbcacacwcqcqx001.bar:8080/speedtest/upload.php",
    "lat": "34.9756",
    "lon": "138.3827",
    "name": "Shizuoka",
    "country": "Japan",
    "cc": "JP",
    "sponsor": "OpenGW",
    "id": "42413",
    "host": "speedtestooklaserverjapannagoyashizuoka.baobivawpvojawvianoipwqnpibvbqoubwuvbqasciboabowbcacacwcqcqx001.bar:8080",
    "d": 64.2282382602239,
    "latency": 73.207
  },
  "timestamp": "2021-06-23T09:19:28.880310Z",
  "bytes_sent": 1515520,
  "bytes_received": 10101900,
  "share": null,
  "client": {
    "ip": "203.0.113.0",
    "lat": "34.733",
    "lon": "137.7439",
    "isp": "freebit",
    "isprating": "3.7",
    "rating": "0",
    "ispdlavg": "0",
    "ispulavg": "0",
    "loggedin": "0",
    "country": "JP"
  }
}
  1. 既定値で実行すると自分のipアドレスのgeoipで近いサーバにpingを打って近そうなサーバを探して速度テストする.(物理的には鹿児島だけどgeoipでは静岡扱いなのでその周りが使われる)
  2. シンプルな表示
  3. 物理的に近そうな九州内のサーバを探す
  4. 物理的に一番近いサーバを指定
  5. csvヘッダを表示(計測はしない)
  6. csv形式で出力
  7. json形式で出力(して jq で整形)

これをcrontabに設定して定期的に実行し,速度の変化を見てみようと思いました.

crontabに */30 * * * * speedtest-cli --csv >> ~/log/speedtest.csv を設定して30分毎に速度テストをして ~/log/speedtest.csv に書き出してみます.

$ mkdir ~/log (1)
$ speedtest-cli --csv-header > ~/log/speedtest.csv (2)
$ crontab -e (3)
$ crontab -l | grep speedtest-cli (4)
*/30 * * * *    speedtest-cli --csv >> ~/log/speedtest.csv
  1. ログ格納ディレクトリ作成
  2. csvヘッダをログファイルに書き込み
  3. crontab -e で以下の行を追加
  4. crontabに登録されているのを確認

しかし,手動で実行時には失敗した頃がないのにcrontab 経由だとほぼ全てが失敗します.まれに成功することもありますが,10回に1回も成功しません.

以下のエラーが出力されます.

ERROR: Unable to connect to servers to test latency.

crontabでだけエラーとなるので,コマンドをshell script fileにしてそれを呼ぶようにしたり,リダイレクト方法を変更してみたり,sourceを見るとサーバリストの取得に失敗しているようなのでサーバを指定するようにしてみたけどサーバを指定してもサーバリストを取得するので意味がなかったりということを試していました.

もしかして毎0分,30分の実行するのが良くないのではと,crontabを以下のように書き換えて6分と36分に実行されるよう変更たところろ動作するようになりました.

$ crontab -l | grep speedtest-cli (1)
6,36 * * * *    speedtest-cli --csv >> ~/log/speedtest.csv

手動でも0分丁度に実行するとエラーになることを確認しました.

$ speedtest-cli
Retrieving speedtest.net configuration...
Testing from freebit (180.131.110.140)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
ERROR: Unable to connect to servers to test latency.

ということでとりあえずきりのいい時間からずらすと動くようになりました.

実はSpeedTest公式のCLI ツールもありこれだと今回の問題は起こらないようです.
バイナリしか提供されていませんが,macOS/Windows/Linux/FreeBSD版が提供されていて,Linuxはi386, x86_64, armlf, armhf, arm64 が提供されています.

こちらを使うと毎0分,30分に実行しても動作しました. csv, tsv, json, jsonl, json-pretty` での出力に対応しているしこちらを使うのもありかもしれません.ただsourceも無いし2019年のリリースからバージョンが上がっていないのでメンテされているのかちょっと不安です.

環境
$ dpkg-query -W speedtest-cli
speedtest-cli   2.1.3-2
$ lsb_release -dr
Description:    Debian GNU/Linux 11 (bullseye)
Release:        11
$ arch
x86_64
]]>
https://matoken.org/blog/2021/07/06/trouble-with-speedtest-cli-not-working-with-crontab/feed/ 1
crontab の実行タイミングをわかりやすく表示してくれる cronv を試す https://matoken.org/blog/2019/05/25/try-cronv-which-gives-a-clear-view-of-crontabs-execution-timing/ https://matoken.org/blog/2019/05/25/try-cronv-which-gives-a-clear-view-of-crontabs-execution-timing/#respond Fri, 24 May 2019 21:51:57 +0000 http://matoken.org/blog/?p=2400

ちょっと試したら少し嵌ったのでメモがてら.

build
$ go get github.com/takumakanari/cronv/cronv
$ go build -o ./cronv github.com/takumakanari/cronv/cronv
Usage
$ ./cronv -h
Usage:
  Cronv v0.4.1 [OPTIONS]

Application Options:
  -o, --output=    path to .html file to output (default: ./crontab.html)
  -d, --duration=  duration to visualize in N{suffix} style. e.g.) 1d(day)/1h(hour)/1m(minute) (default: 6h)
      --from-date= start date in the format '2006/01/02' to visualize (default: 2019/05/25)
      --from-time= start time in the format '15:04' to visualize (default: 02:50)
  -t, --title=     title/label of output (default: Cron Tasks)
  -w, --width=     Table width of output (default: 100)

Help Options:
  -h, --help       Show this help message
実行
$ crontab -l | ./cronv

2019-06-01 ADD: 以下のtab が含まれているときにエラーとなる問題は修正されました😖

しかし,missing field(s) とか syntax error in year field: とかのエラーになってしまう.

$ printf "* * * * *\tcommand\n"
* * * * *       command
$ printf "* * * * *\tcommand\n" | ./cronv
panic: Failed to analyze cron '* * * * *        command': syntax error in year field: 'command'

goroutine 1 [running]:
panic
        ../../../src/libgo/go/runtime/panic.go:554
main.main
        /home/mk/go/src/github.com/takumakanari/cronv/cronv/main.go:33

タブ区切りをやめてスペース区切りにするとエラーが出ない

$ printf "* * * * * command\n" | ./cronv
[Cron Tasks] 1 tasks.
[Cron Tasks] './crontab.html' generated.

ということでとりあえずタブをスペースに変換することにした.

$ crontab -l | tr -s '\t' ' ' | ./cronv
[Cron Tasks] 8 tasks.
[Cron Tasks] './crontab.html' generated.

作成された crontab.html を w3m で……ほとんど表示されない.

20190525 03 36 35 001

もう少しリッチな JavaScript の動くウェブブラウザで開くとOK.
これからの6時間分の様子が見える.

20190525 03 00 01 001

-d, --duration option で表示する時間間隔が指定できる.
開始日時は,--fron-date, --from-time option で指定できる.
以下の例では 2019-05-25 00:00:00 から1日分の表示になる.

$ crontab -l | tr -s '\t' ' ' | ./cronv -d 1d --from-date=2019/05/25 --from-time=00:00

20190525 02 58 37 001

ちなみに1ヶ月も試したが,ウェブブラウザで表示するのにとても時間が掛かった.

環境
$ dpkg-query -W cron gccgo-go
cron    3.0pl1-128.1ubuntu1
gccgo-go        2:1.10~4ubuntu1
$ lsb_release -d
Description:    Ubuntu 18.04.2 LTS
$ uname -m
x86_64

]]>
https://matoken.org/blog/2019/05/25/try-cronv-which-gives-a-clear-view-of-crontabs-execution-timing/feed/ 0
crontab から送信される電子メールの件名を指定したい https://matoken.org/blog/2018/09/16/i-want-to-specify-the-subject-of-e-mail-sent-from-crontab/ https://matoken.org/blog/2018/09/16/i-want-to-specify-the-subject-of-e-mail-sent-from-crontab/#respond Sat, 15 Sep 2018 22:18:17 +0000 http://matoken.org/blog/?p=2116

crontab で実行されたコマンドの出力はメールで送られますが,このときの件名は「Cron <ユーザ名@ホスト名> 実行コマンド」のようになります.

crontab 例
15 7 * * *  echo "cron subject"
メール例
Subject: Cron <matoken@T430s> echo "cron subject"

cron subject
1つのhostからこんなメール飛んで来るとどれがどれかわかりづらい
Cron <matoken@T430s> nice -n 19 ionice -c 3 rsync -avxze "ssh -i……
Cron <root@T430s> nice -n 19 ionice -c 3 rsync -avxze "ssh -i……
Cron <root@T430s> nice -n 19 ionice -c 3 rsync -avxze "ssh -i……

分かりづらいので自分で件名を付けたいところです.

: を利用する

: は shell の組み込み関数で何もせず正常終了します.
コマンドなので # と違い,; の後にコマンドを書くとその後のコマンドは解釈されます.

$ :           #何もしない
$ : hoge
$ : echo hoge
$ : rm -rf *
$ : $(hostname)  #コマンドも展開せず何もしない
$ : `whoami`
$ : hoge; echo fuga   #;の後は解釈される
fuga
$ # hoge
$ # hoge; echo fuga

これをcrontabの頭に書くとこういう感じになります.

crontab
29 6 * * *  : cron subject; echo "hello"
mail
Subject: Cron <matoken@T430s> : cron subject; echo "hello"

hello

少しわかりやすくなりました.

mailコマンドを利用する

これはちょっと反則な感じがするのですが件名にコマンド実行結果を入れたり,頭の部分も書き換えたい場合はcronだけではできなさそうなのでmailコマンド経由で送信してみます.今回mailutilsのmailコマンドを利用しましたが,bsd-mailxやmutt等々ももちろん使えます.

crontab
45 6 * * *  echo "cron test" | mail -s "$(hostname)@$(whoami) cron Subject : $(date +\%F)" matoken+cron@example.com
mail
Subject: T430s@matoken cron Subject : 2018-09-13
X-Mailer: mail (GNU Mailutils 3.4)

cron test

mail コマンドの -s オプション部分が件名になります.その後ろが宛先のメールアドレス.bodyはcronの出力をパイプから受け取ります.

STDERR が別メールで届く

STDERR の出力があった場合cronでメールが送られてしまいます.mailコマンドと合わせて1度に2通届くことに.
実行コマンドの後ろに 2>&1 を付けて STDERR を STDOUT に渡してmailコマンドだけにします.

crontab
45 6 * * *  echo "cron test" 2>&1 | mail -s "$(hostname)@$(whoami) cron Subject : $(date +\%F)" matoken+cron@example.com

出力がなくてもメールが届く

crontab の場合コマンドの出力がなければメールが送られませんが,このコマンドでは NULL でもメールが送信されます.
未解決.

余録

cronで一切メールを送りたくない

場合crontabで MAILTO=”” を設定する
MAILTO=""

指定したコマンドだけメールを送りたくない

STDOUT と STDERR を /dev/null に捨てる
20 6 * * *  echo "cron subject" > /dev/null 2>&1

メールが届かない

/var/spool/mail/ユーザ名 のローカルにはメールがどとくけど,インターネット上のメールアドレスを指定しても届かない場合メールサーバの設定が出来ていないかもしれません.メールサーバ(sSMTP/msmtp等はデーモンが起動しないのでメールを受け取らず送信するだけならおすすめ)を設定してから再度試してみましょう.

環境1
$ man cron | grep -m1 cron
       cron - daemon to execute scheduled commands (Vixie Cron)
$ dpkg-query -W cron mailutils
cron    3.0pl1-128.1ubuntu1
mailutils       1:3.4-1
$ lsb_release -d
Description:    Ubuntu 18.04.1 LTS
$ uname -m
x86_64
環境2
$ man cron | grep -m1 cron
       cron - 予定されたコマンドを実行するデーモン(Vixie Cron)
$ dpkg-query -W cron mailutils
cron    3.0pl1-130
mailutils       1:3.4-1+b1
$ lsb_release -d
Description:    Debian GNU/Linux unstable (sid)
$ uname -m
x86_64
]]>
https://matoken.org/blog/2018/09/16/i-want-to-specify-the-subject-of-e-mail-sent-from-crontab/feed/ 0